#pragma once

#include <vcclr.h>

namespace Vortex { namespace Wrapper { namespace Direct3D {

	public interface struct ShaderConstantCallback {
		void SetVertexShaderConstantF(UINT startRegister, const float* pData, UINT vector4fCount);
		void SetVertexShaderConstantI(UINT startRegister, const int* pData, UINT vector4iCount);
		void SetVertexShaderConstantB(UINT startRegister, const BOOL* pData, UINT boolCount);
		void SetPixelShaderConstantF(UINT startRegister, const float* pData, UINT vector4fCount);
		void SetPixelShaderConstantI(UINT startRegister, const int* pData, UINT vector4iCount);
		void SetPixelShaderConstantB(UINT startRegister, const BOOL* pData, UINT boolCount);
	};

	class D3DDeviceProxy : public IDirect3DDevice9 {
		gcroot<ShaderConstantCallback^> _callback;
	public:

		D3DDeviceProxy(gcroot<ShaderConstantCallback^> callback) : _callback(callback) {
		}

		/*** IUnknown methods ***/
		STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) { return E_NOTIMPL; };
		STDMETHOD_(ULONG,AddRef)(THIS) { return 0; };
		STDMETHOD_(ULONG,Release)(THIS) { return 0; };

		/*** IDirect3DDevice9 methods ***/
		STDMETHOD(TestCooperativeLevel)(THIS) { return E_NOTIMPL; };
		STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) { return E_NOTIMPL; };
		STDMETHOD(EvictManagedResources)(THIS) { return E_NOTIMPL; };
		STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9) { return E_NOTIMPL; };
		STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps) { return E_NOTIMPL; };
		STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain,D3DDISPLAYMODE* pMode) { return E_NOTIMPL; };
		STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters) { return E_NOTIMPL; };
		STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot,UINT YHotSpot,IDirect3DSurface9* pCursorBitmap) { return E_NOTIMPL; };
		STDMETHOD_(void, SetCursorPosition)(THIS_ int X,int Y,DWORD Flags) { };
		STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow) { return FALSE; };
		STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DSwapChain9** pSwapChain) { return E_NOTIMPL; };
		STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain,IDirect3DSwapChain9** pSwapChain) { return E_NOTIMPL; };
		STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) { return 0; };
		STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) { return E_NOTIMPL; };
		STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) { return E_NOTIMPL; };
		STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain,UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9** ppBackBuffer) { return E_NOTIMPL; };
		STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain,D3DRASTER_STATUS* pRasterStatus) { return E_NOTIMPL; };
		STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) { return E_NOTIMPL; };
		STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp) { };
		STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain,D3DGAMMARAMP* pRamp) { };
		STDMETHOD(CreateTexture)(THIS_ UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,HANDLE* pSharedHandle) { return E_NOTIMPL; };
		STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,HANDLE* pSharedHandle) { return E_NOTIMPL; };
		STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,HANDLE* pSharedHandle) { return E_NOTIMPL; };
		STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,HANDLE* pSharedHandle) { return E_NOTIMPL; };
		STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,HANDLE* pSharedHandle) { return E_NOTIMPL; };
		STDMETHOD(CreateRenderTarget)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) { return E_NOTIMPL; };
		STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) { return E_NOTIMPL; };
		STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) { return E_NOTIMPL; };
		STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture,IDirect3DBaseTexture9* pDestinationTexture) { return E_NOTIMPL; };
		STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface) { return E_NOTIMPL; };
		STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,IDirect3DSurface9* pDestSurface) { return E_NOTIMPL; };
		STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter) { return E_NOTIMPL; };
		STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface,CONST RECT* pRect,D3DCOLOR color) { return E_NOTIMPL; };
		STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) { return E_NOTIMPL; };
		STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget) { return E_NOTIMPL; };
		STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget) { return E_NOTIMPL; };
		STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil) { return E_NOTIMPL; };
		STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface) { return E_NOTIMPL; };
		STDMETHOD(BeginScene)(THIS) { return E_NOTIMPL; };
		STDMETHOD(EndScene)(THIS) { return E_NOTIMPL; };
		STDMETHOD(Clear)(THIS_ DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) { return E_NOTIMPL; };
		STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) { return E_NOTIMPL; };
		STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) { return E_NOTIMPL; };
		STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE,CONST D3DMATRIX*) { return E_NOTIMPL; };
		STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport) { return E_NOTIMPL; };
		STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport) { return E_NOTIMPL; };
		STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial) { return E_NOTIMPL; };
		STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial) { return E_NOTIMPL; };
		STDMETHOD(SetLight)(THIS_ DWORD Index,CONST D3DLIGHT9*) { return E_NOTIMPL; };
		STDMETHOD(GetLight)(THIS_ DWORD Index,D3DLIGHT9*) { return E_NOTIMPL; };
		STDMETHOD(LightEnable)(THIS_ DWORD Index,BOOL Enable) { return E_NOTIMPL; };
		STDMETHOD(GetLightEnable)(THIS_ DWORD Index,BOOL* pEnable) { return E_NOTIMPL; };
		STDMETHOD(SetClipPlane)(THIS_ DWORD Index,CONST float* pPlane) { return E_NOTIMPL; };
		STDMETHOD(GetClipPlane)(THIS_ DWORD Index,float* pPlane) { return E_NOTIMPL; };
		STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD Value) { return E_NOTIMPL; };
		STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD* pValue) { return E_NOTIMPL; };
		STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type,IDirect3DStateBlock9** ppSB) { return E_NOTIMPL; };
		STDMETHOD(BeginStateBlock)(THIS) { return E_NOTIMPL; };
		STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB) { return E_NOTIMPL; };
		STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus) { return E_NOTIMPL; };
		STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus) { return E_NOTIMPL; };
		STDMETHOD(GetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9** ppTexture) { return E_NOTIMPL; };
		STDMETHOD(SetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9* pTexture) { return E_NOTIMPL; };
		STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) { return E_NOTIMPL; };
		STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) { return E_NOTIMPL; };
		STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD* pValue) { return E_NOTIMPL; };
		STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value) { return E_NOTIMPL; };
		STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) { return E_NOTIMPL; };
		STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber,CONST PALETTEENTRY* pEntries) { return E_NOTIMPL; };
		STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber,PALETTEENTRY* pEntries) { return E_NOTIMPL; };
		STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber) { return E_NOTIMPL; };
		STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber) { return E_NOTIMPL; };
		STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect) { return E_NOTIMPL; };
		STDMETHOD(GetScissorRect)(THIS_ RECT* pRect) { return E_NOTIMPL; };
		STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware) { return E_NOTIMPL; };
		STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS) { return FALSE; };
		STDMETHOD(SetNPatchMode)(THIS_ float nSegments) { return E_NOTIMPL; };
		STDMETHOD_(float, GetNPatchMode)(THIS) { return 0.0f; }
		STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) { return E_NOTIMPL; };
		STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount) { return E_NOTIMPL; };
		STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) { return E_NOTIMPL; };
		STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) { return E_NOTIMPL; };
		STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer9* pDestBuffer,IDirect3DVertexDeclaration9* pVertexDecl,DWORD Flags) { return E_NOTIMPL; };
		STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl) { return E_NOTIMPL; };
		STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl) { return E_NOTIMPL; };
		STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl) { return E_NOTIMPL; };
		STDMETHOD(SetFVF)(THIS_ DWORD FVF) { return E_NOTIMPL; };
		STDMETHOD(GetFVF)(THIS_ DWORD* pFVF) { return E_NOTIMPL; };
		STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader) { return E_NOTIMPL; };
		STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader) { return E_NOTIMPL; };
		STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader) { return E_NOTIMPL; };

		STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount) { return E_NOTIMPL; };
		STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount) { return E_NOTIMPL; };
		STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount) { return E_NOTIMPL; };

		STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) { 
			_callback->SetVertexShaderConstantF(StartRegister, pConstantData, Vector4fCount);
			return S_OK;
		};

		STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) {
			_callback->SetVertexShaderConstantI(StartRegister, pConstantData, Vector4iCount);
			return S_OK;
		};
		
		STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT  BoolCount) { 
			_callback->SetVertexShaderConstantB(StartRegister, pConstantData, BoolCount);
			return S_OK;
		};

		STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride) { return E_NOTIMPL; };
		STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9** ppStreamData,UINT* OffsetInBytes,UINT* pStride) { return E_NOTIMPL; };
		STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT Divider) { return E_NOTIMPL; };
		STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT* Divider) { return E_NOTIMPL; };
		STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData) { return E_NOTIMPL; };
		STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData) { return E_NOTIMPL; };
		STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader) { return E_NOTIMPL; };
		STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader) { return E_NOTIMPL; };
		STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader) { return E_NOTIMPL; };
		
		STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount) { return E_NOTIMPL; };
		STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount) { return E_NOTIMPL; };
		STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount) { return E_NOTIMPL; };
		
		STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) {
			_callback->SetPixelShaderConstantF(StartRegister, pConstantData, Vector4fCount);
			return S_OK;
		}
		
		STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) {
			_callback->SetPixelShaderConstantI(StartRegister, pConstantData, Vector4iCount);
			return S_OK;
		}
		
		STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT  BoolCount) {
			_callback->SetPixelShaderConstantB(StartRegister, pConstantData, BoolCount);
			return S_OK;
		}
		
		STDMETHOD(DrawRectPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) { return E_NOTIMPL; };
		STDMETHOD(DrawTriPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) { return E_NOTIMPL; };
		STDMETHOD(DeletePatch)(THIS_ UINT Handle) { return E_NOTIMPL; };
		STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery) { return E_NOTIMPL; };
	};

} } }